﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Hukee.ExcelHelper
{
    /// <summary>
    /// Excel数据结构
    /// </summary>
    public class ExcelData
    {
        // 文件名称
        private string fileName;

        /// <summary>
        /// 文件名称
        /// </summary>
        public string ExcelFileName
        {
            get { return fileName; }
            set
            {
                fileName = value;
                if (!fileName.EndsWith(".xlsx")) fileName += ".xlsx";
            }
        }

        /// <summary>
        /// Excel的sheet分页列表
        /// </summary>
        private ICollection<ExcelSheetData> sheetItem;

        public ExcelData(ICollection<ExcelSheetData> inputItem, string excelFileName= "defaultName.xlsx")
        {
            sheetItem = inputItem;
            ExcelFileName = excelFileName;
        }

        public ExcelData()
        {
            ExcelFileName = "defaultName.xlsx";
            sheetItem = new List<ExcelSheetData>();
        }

        public void AddSheetData(ExcelSheetData excelSheet)
        {
            sheetItem.Add(excelSheet);
        }

        public void AddSheetDataList(ICollection<ExcelSheetData> excelSheetList)
        {
            foreach (var item in excelSheetList) sheetItem.Add(item);
        }

        /// <summary>
        /// 获取sheet分页配置集
        /// </summary>
        /// <returns></returns>
        public ICollection<ExcelSheetData> GetSheetList()
        {
            return sheetItem;
        }

    }

    /// <summary>
    /// Excel的Sheet分页数据结构
    /// </summary>
    public class ExcelSheetData
    {
        /// <summary>
        /// 文件名称
        /// </summary>
        private string sheetName;

        /// <summary>
        /// 文件名称
        /// </summary>
        private string fileName = "excel.xlsx";

        /// <summary>
        /// 二维数组数据
        /// </summary>
        private object[,] data;

        /// <summary>
        /// 行数
        /// </summary>
        private int rows;

        /// <summary>
        /// 列数
        /// </summary>
        private int Columns;

        public bool NeedMerge { get; set; } = false;

        /// <summary>
        /// 字体样式设置<br/>
        /// key: 所属列数
        /// value: 字体样式参数
        /// </summary>
        public Dictionary<int,ExcelStyle[]> ExcelStyleDic { get; set; }

        public ExcelSheetData(string sheetName, object[,] excelData, Dictionary<int, ExcelStyle[]> excelForntList)
        {
            ExcelSheetDataInit(sheetName, excelData);
            ExcelStyleDic = excelForntList;
        }

        public ExcelSheetData(string sheetName, object[,] excelData)
        {
            ExcelSheetDataInit(sheetName, excelData);
        }

        public ExcelSheetData(object[,] excelData)
        {
            ExcelSheetDataInit(string.Empty, excelData);
        }

        private void ExcelSheetDataInit(string sheetName, object[,] excelData)
        {
            if (string.IsNullOrWhiteSpace(sheetName)) this.sheetName = "sheet0";
            else this.sheetName = sheetName;
            data = excelData;
            rows = data.GetLength(0);
            Columns = data.GetLength(1);
        }

        /// <summary>
        /// sheet分页名称
        /// </summary>
        public string ExcelSheetName
        {
            get { return sheetName; }
            set
            {
                sheetName = value;
            }
        }

        /// <summary>
        /// 文件名称
        /// </summary>
        public string ExcelFileName
        {
            get { return fileName; }
            set
            {
                fileName = value;
                if (!fileName.EndsWith(".xlsx"))
                {
                    fileName += ".xlsx";
                }
            }
        }

        /// <summary>
        /// excel二维数组数据
        /// </summary>
        public object[,] ExcelArrayData
        {
            get { return data; }
            set
            {
                data = value;
                rows = data.GetLength(0);
                Columns = data.GetLength(1);
                mergeInfos = null;
            }
        }

        /// <summary>
        /// 获取标题行（即excel二维数组数据的首行）
        /// </summary>
        public object[] GetExcelTitleRows
        {
            get
            {
                object[] result = new string[Columns];
                for (int i = 0; i < Columns; i++)
                {
                    result[i] = data[0, i];
                }
                return result;
            }
        }

        /// <summary>
        /// 获取行数
        /// </summary>
        /// <returns></returns>
        public int RowLength()
        {
            return rows;
        }

        /// <summary>
        /// 获取列数
        /// </summary>
        /// <returns></returns>
        public int ColumnLength()
        {
            return Columns;
        }

        /// <summary>
        /// 获取excel中某行某列的数据值
        /// </summary>
        /// <param name="x">行</param>
        /// <param name="y">列</param>
        /// <returns></returns>
        public object GetDataByCoordinate(int x, int y)
        {
            return data[x, y];
        }

        /// <summary>
        /// 获取excel中某行某列的数据值
        /// </summary>
        /// <param name="x">行</param>
        /// <param name="y">列</param>
        /// <returns></returns>
        public object this[int x, int y]
        {
            get { return data[x, y]; }
            set { data[x, y] = value; }
        }

        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < Columns; j++)
                {
                    builder.Append(data[i, j] + "\t");
                }
                builder.AppendLine();
            }
            return builder.ToString();
        }

        private List<MergeInfo> mergeInfos;
        /// <summary>
        ///  获取可合并的行列数据信息
        /// </summary>
        public List<MergeInfo> MergeInfos { get => mergeInfos ?? GetMergeInfos(); }

        /// <summary>
        /// 获取可合并的行列数据信息
        /// </summary>
        /// <returns></returns>
        private List<MergeInfo> GetMergeInfos()
        {
            mergeInfos = new List<MergeInfo>();

            bool[,] dynamicTable = new bool[RowLength() - 1, ColumnLength()];
            
            //数据列 输入
            for (int j = 0; j < ColumnLength(); j++)
            {
                int x = 1;
                for (int i = 2; i < RowLength(); i++)
                {
                    if (this[i, j] == this[i - 1, j])
                    {
                        dynamicTable[i - 2, j] = j == 0 ? true : dynamicTable[i - 2, j - 1];
                        if (i == RowLength() - 1 || dynamicTable[i - 2, j] == false)
                        {
                            if (x != i - 1)
                            {
                                mergeInfos.Add(new MergeInfo
                                {
                                    X = x,
                                    Y = j,
                                    X_Merge = i == (RowLength() - 1) && (dynamicTable[i - 2, j]) ? i : i - 1,
                                    Y_Merge = j
                                });
                            }
                            x = i;
                        }
                    }
                    else
                    {
                        dynamicTable[i - 2, j] = false;
                        if (x != i - 1)
                        {
                            mergeInfos.Add(new MergeInfo
                            {
                                X = x,
                                Y = j,
                                X_Merge = i - 1,
                                Y_Merge = j
                            });
                        }
                        x = i;
                    }
                }
            }
            return mergeInfos;
        }

        /// <summary>
        /// 合并行列坐标组
        /// </summary>
        public class MergeInfo
        {
            public int X { get; set; }
            public int Y { get; set; }
            public int X_Merge { get; set; }
            public int Y_Merge { get; set; }
        }
    }

}
